/*
 * This file is part of Shopping Lists Organizer software
 *
 * Copyright (C) 2011 Denis Kvita <dkvita@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#include <QtGui>
#include <QtSql>

#include "shopmodel.h"

shopModel::shopModel(QObject *parent) :
	QAbstractTableModel(parent),cc()
{
	fieldNames<<"sTitle"<<"sAddress"<<"joy"<<"lists"<<"purchases"<<"costP"<<"costB";
}

int shopModel::rowCount(const QModelIndex &parent) const
{
	QSqlDatabase dbc= QSqlDatabase::database("CN");
	QSqlQuery q(dbc);
	q.prepare("SELECT count(*) FROM shop");
	q.exec();

	if(q.next()){
		return q.value(0).toInt();
	}
	return 0;
}

int shopModel::columnCount(const QModelIndex &parent) const
{
	return 7;
}


QVariant shopModel::data(const QModelIndex &index, int role) const
{
	if(role == Qt::DisplayRole || role == Qt::EditRole){
		return cc.value(index.row()).value(index.column());
	}
	if( index.column() >1 && role == Qt::BackgroundRole ) return QBrush(QColor(255,255,0,128));
	return QVariant();
}

QVariant shopModel::headerData(int section, Qt::Orientation orientation, int role) const
{
	if(orientation == Qt::Horizontal){
		if(role == Qt::DisplayRole){
			switch(section){
			case 0: return tr("shop");
			break;
			case 1: return tr("address");
			break;
			case 2: return tr("average joy");
			break;
			case 3: return tr("lists");
			break;
			case 4: return tr("purchases");
			break;
			case 5: return tr("total planned");
			break;
			case 6: return tr("total bought");
			break;
			default: return QAbstractTableModel::headerData(section, orientation, role);
			}
		}
	}else{
		;
	}
	return QAbstractTableModel::headerData(section, orientation, role);
}

bool shopModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
	QSqlDatabase dbc= QSqlDatabase::database("CN");
	QSqlQuery q(dbc);

	if(value == cc.value(index.row()).value(index.column())) return true;
	if(role == Qt::EditRole || role == Qt::DisplayRole){
		int shopID= cc.value(index.row()).value(7).toInt();
		q.prepare(QString("UPDATE shop SET "+fieldNames.at(index.column())+"=:V WHERE oid=:ID"));
		q.bindValue(":V",value);
		q.bindValue(":ID",shopID);
		if(!q.exec() || q.numRowsAffected()<1){
			return false;
		}
	}
	cc[index.row()].setValue(index.column(),value);
	emit dataChanged(index,index);
	return true;
}

Qt::ItemFlags shopModel::flags(const QModelIndex & index) const
{
	Qt::ItemFlags f= Qt::ItemIsEnabled|(index.column() > 1 ? Qt::NoItemFlags: Qt::ItemIsSelectable|Qt::ItemIsEditable);
	return f;
}

bool shopModel::insertRows(int row, int count, const QModelIndex & parent)
{
	if(count<=0) return false;
	beginInsertRows(parent, row, row+count-1);
	endInsertRows();
	return true;
}

bool shopModel::removeRows(int row, int count, const QModelIndex & parent)
{
	if(count<=0) return false;
	beginRemoveRows(parent, row, row+count-1);
	endRemoveRows();
	return true;
}

void shopModel::clear()
{
	beginResetModel();
	removeRows(0,rowCount());
	cc.clear();
	insertRows(0,rowCount());
	endResetModel();
}

void shopModel::restore()
{
	cc.clear();
	beginResetModel();
	removeRows(0,rowCount());

	QSqlDatabase dbc= QSqlDatabase::database("CN");
	QSqlQuery q(dbc);
	q.prepare("SELECT sTitle,sAddress,(SELECT avg(pJoy) FROM purchase WHERE pShop=shop.oid) as joy"
			  ",(SELECT count(*) FROM (SELECT DISTINCT pDate,pList FROM purchase WHERE pShop==shop.oid)) as lists"
			  ",(SELECT count(*) FROM purchase WHERE pShop=shop.oid) as purchases"
			  ",(SELECT sum(pPrcP*pCntP) FROM purchase WHERE pShop=shop.oid) as costP"
			  ",(SELECT sum(pPrcB*pCntB) FROM purchase WHERE pShop=shop.oid) as costB"
			  ",oid FROM shop ORDER BY sTitle");
	q.exec();
	while(q.next()){
		cc.append(QSqlRecord(q.record()));
	}

	insertRows(0,rowCount());
	endResetModel();
}

QModelIndex shopModel::addEmpty()
{
	int r=rowCount();
	QSqlDatabase dbc= QSqlDatabase::database("CN");
	dbc.transaction();
	QSqlQuery q(dbc);
	q.prepare("INSERT INTO shop(sTitle,sAddress,sGeoLoc) VALUES("+tr("'New Shop'")+",NULL,NULL)");
	if(!q.exec()){
		dbc.rollback();
		return QModelIndex();
	}

	q.prepare("SELECT sTitle,sAddress,(SELECT avg(pJoy) FROM purchase WHERE pShop=shop.oid) as joy"
			  ",(SELECT count(*) FROM (SELECT DISTINCT pDate,pList FROM purchase WHERE pShop==shop.oid)) as lists"
			  ",(SELECT count(*) FROM purchase WHERE pShop=shop.oid) as purchases"
			  ",(SELECT sum(pPrcP*pCntP) FROM purchase WHERE pShop=shop.oid) as costP"
			  ",(SELECT sum(pPrcB*pCntB) FROM purchase WHERE pShop=shop.oid) as costB"
			  ",oid FROM shop WHERE oid=last_insert_rowid();");
	if(!q.exec() || !q.next()){
		dbc.rollback();
		return QModelIndex();
	}
	cc.append(QSqlRecord(q.record()));
	dbc.commit();
	insertRows(r,1);
	return QAbstractTableModel::index(r,0);
}

bool shopModel::rem(int row)
{
	if(rowid(row)<0) return false;
	QSqlDatabase dbc= QSqlDatabase::database("CN");
	QSqlQuery q(dbc);
	q.prepare(QString("DELETE FROM shop WHERE oid=:ID"));
	q.bindValue(":ID", rowid(row));
	if(q.exec()){
		q.prepare("UPDATE purchase SET pShop=NULL WHERE pShop=:SID");
		q.bindValue(":SID", rowid(row));
		q.exec();
		cc.removeAt(row);
		return removeRows(row,1);
	}
	return true;
}

int shopModel::rowid(int row)
{
	if(cc.count()>row) return cc.value(row).value(7).toInt();
	return -1;
}
